//============================================================================
// Name        : LogViewer.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================


#include "LogRecords.h"
#include <fstream>
using namespace std;
using namespace Taller2::TransRec;

int main(int argc, char** argv)
{
	fstream output;
	if(argc<2)
	{
		printf("ERROR!");
		return -1;
	}
	string dataBase = argv[1];
	output.open("ViewLog.log", ios_base::out | ios_base::trunc);
	if (output.is_open())
	{
		int logsize = 0;
		fstream logfile;
		logfile.open(dataBase.data(), ios_base::in);

		logfile.seekg(0, ios_base::end);
		logsize = logfile.tellg();
		logfile.seekg(0, ios_base::beg);
		if (logfile.is_open())
		{
			CLogRecord *reg = NULL;

			output << "Log File: "  << dataBase.data() << endl;
			output << endl;
			output << "File size: " << logsize << " bytes" << endl;
			output << endl;

			int regnum     = 0;
			int byteoffset = 0;

			output << endl;
			output << "*************************************************";
			output << endl;

			CLogRecord::CreateRecord(logfile, reg);

			while (reg != NULL)
			{
				output << "Registro Numero: " << regnum << endl;
				if (reg->EntryType() == INSERT)
				{
					CInsertRecord *ins = reinterpret_cast<CInsertRecord*>(reg);
					output << byteoffset << ":" << byteoffset+sizeof(LogEntryType)-1 << "\tTipo: INSERT" << endl;
					byteoffset += sizeof(LogEntryType);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<  "\tLSN: " << ins->GetLSN()	<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<  "\tLastLSN Same Transaction: " << ins->LastLSNSameTransaction()	<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset+sizeof(int)-1 << "\tTimestamp: " << ins->TimeStamp()<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<  "\tTransactionID: "	<< ins->TransactionID()	<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(long long int)-1 <<  "\tObject ID: "	<< ins->ObjectID()	<< endl;
					byteoffset += sizeof(long long int);

					//output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tOld Object Size: 0" << endl;
					//byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<  "\tNew Object size: "	<< ins->ObjectSize() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + ins->ObjectSize()-1 << "\tDATA" << endl;
					byteoffset += ins->ObjectSize();

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<  "\tLastLSN: " << ins->LastLSN()	<< endl;
					byteoffset += sizeof(int);

					ins = NULL;

				}else if (reg->EntryType() == DELETE)
				{
					CDeleteRecord *del = reinterpret_cast<CDeleteRecord*>(reg);
					output << byteoffset << ":" << byteoffset + sizeof(LogEntryType)-1 <<  "\tTipo: DELETE"	<< endl;
					byteoffset += sizeof(LogEntryType);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tLSN: "	<< del->GetLSN() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tLastLSN Same Transaction: " << del->LastLSNSameTransaction() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tTimestamp: " << del->TimeStamp() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tTransactionID: "	<< del->TransactionID() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(long long int)-1 <<   "\tObject ID: "	<< del->ObjectID()	<< endl;
					byteoffset += sizeof(long long int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tOld Object size: "	<< del->ObjectSize() << endl;
					byteoffset += sizeof(int);

					//output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tNew Object Size: 0" << endl;
					//byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + del->ObjectSize()-1 << "\tDATA" << endl;
					byteoffset += del->ObjectSize();

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 <<   "\tLastLSN: " << del->LastLSN() << endl;
					byteoffset += sizeof(int);

					del = NULL;

				}else if (reg->EntryType() == UPDATE)
				{
					CUpdateRecord *upd = reinterpret_cast<CUpdateRecord*>(reg);
					output  << byteoffset << ":" << byteoffset + sizeof(LogEntryType)-1 <<   "\tTipo: UPDATE"  << endl;
					byteoffset += sizeof(LogEntryType);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tLSN: "						 << upd->GetLSN()					  << endl;
					byteoffset += sizeof(int);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tLastLSN Same Transaction: " << upd->LastLSNSameTransaction() << endl;
					byteoffset += sizeof(int);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tTimestamp: "				 << upd->TimeStamp()			  << endl;
					byteoffset += sizeof(int);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tTransactionID: "			 << upd->TransactionID()		  << endl;
					byteoffset += sizeof(int);

					output  << byteoffset << ":" << byteoffset + sizeof(long long int)-1 <<    "\tObject ID: " << upd->ObjectID()				  << endl;
					byteoffset += sizeof(long long int);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tOld Object size: "	<< upd->OldObjectSize()		  << endl;
					byteoffset += sizeof(int);

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 <<    "\tNew Object size: " << upd->NewObjectSize()		  << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + upd->OldObjectSize()-1 << "\tOLD DATA" << endl;
					byteoffset += upd->OldObjectSize();

					output << byteoffset << ":" << byteoffset + upd->NewObjectSize()-1 << "\tNEW DATA" << endl;
					byteoffset += upd->NewObjectSize();

					output  << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN: " << upd->LastLSN() << endl;
					byteoffset += sizeof(int);

					upd = NULL;

				}else if (reg->EntryType() == COMMIT)
				{
					CCommitRecord *com = reinterpret_cast<CCommitRecord*>(reg);
					output << byteoffset << ":" << byteoffset + sizeof(LogEntryType)-1 << "\tTipo: COMMIT" << endl;
					byteoffset += sizeof(LogEntryType);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLSN: " << com->GetLSN()<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN Same Transaction: " << com->LastLSNSameTransaction() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tTimestamp: " 	<< com->TimeStamp() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tTransactionID: "	<< com->TransactionID() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN: " << com->LastLSN() << endl;
					byteoffset += sizeof(int);

					com = NULL;

				}else if (reg->EntryType() == ROLLBACK)
				{
					CRollbackRecord *roll = reinterpret_cast<CRollbackRecord*>(reg);
					output << byteoffset << ":" << byteoffset + sizeof(LogEntryType)-1 << "\tTipo: ROLLBACK"	<< endl;
					byteoffset += sizeof(LogEntryType);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLSN: " << roll->GetLSN()	<< endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN Same Transaction: "	<< roll->LastLSNSameTransaction() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tTimestamp: "	<< roll->TimeStamp() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tTransactionID: "	<< roll->TransactionID() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN: " << roll->LastLSN() << endl;
					byteoffset += sizeof(int);

					roll = NULL;

				}else if (reg->EntryType() == CHECKPOINT)
				{
					output << byteoffset << ":" << byteoffset + sizeof(LogEntryType)-1 << "\tTipo: CHECKPOINT" << endl;
					byteoffset += sizeof(LogEntryType);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLSN: " << reg->GetLSN() << endl;
					byteoffset += sizeof(int);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tTimestamp: "	<< reg->TimeStamp() << endl;
					byteoffset += sizeof(int);

					CCheckPointRecord *check = reinterpret_cast<CCheckPointRecord*>(reg);

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tCantidad: " << check->GetTransactionMap().size() << endl;
					byteoffset += sizeof(int);

					int i=0;
					//for (CCheckPointRecord::CheckpointMap::iterator it = check->GetTransactionMap().begin(); it != check->GetTransactionMap().end(); it++)
					CCheckPointRecord::CheckpointMap::iterator it = check->GetTransactionMap().begin();
					while(i< check->GetTransactionMap().size())
					{

						i++;
						output  << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\t\tID de transaccion: " << it->first  << endl;
						byteoffset += sizeof(int);

						output  << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\t\tLSN: "	<< it->second << endl;
						byteoffset += sizeof(int);

						it++;
					};

					output << byteoffset << ":" << byteoffset + sizeof(int)-1 << "\tLastLSN: " << reg->LastLSN()	<< endl;
					byteoffset += sizeof(int);

					check = NULL;
				};

				delete reg;
				reg = NULL;
				regnum++;
				output << endl;
				output << "*************************************************";
				output << endl;
				CLogRecord::CreateRecord(logfile, reg);
			};
			logfile.flush();
			logfile.close();
			output.flush();
			output.close();
		};
	};
};
